From f7d2be903b7296434d1f1c69e9d9a6f2ac221e11 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 20 Oct 2006 10:34:24 +0100 Subject: [PATCH] [HVM] Fix oprofile for HVM guests. Signed-off-by: Tom Woller Signed-off-by: Mats Petersson Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/x86_32/exits.S | 2 ++ xen/arch/x86/hvm/svm/x86_64/exits.S | 2 ++ xen/arch/x86/oprofile/op_model_athlon.c | 30 ++++++++++++++------ xen/arch/x86/oprofile/op_model_p4.c | 10 ++----- xen/arch/x86/oprofile/op_model_ppro.c | 10 ++----- xen/arch/x86/oprofile/xenoprof.c | 37 +++++++++++++++++-------- 6 files changed, 56 insertions(+), 35 deletions(-) diff --git a/xen/arch/x86/hvm/svm/x86_32/exits.S b/xen/arch/x86/hvm/svm/x86_32/exits.S index 99a08cd483..a2714030fd 100644 --- a/xen/arch/x86/hvm/svm/x86_32/exits.S +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S @@ -126,6 +126,8 @@ ENTRY(svm_asm_do_launch) HVM_SAVE_ALL_NOSEGREGS STGI +.globl svm_stgi_label; +svm_stgi_label: movl %esp,%eax push %eax call svm_vmexit_handler diff --git a/xen/arch/x86/hvm/svm/x86_64/exits.S b/xen/arch/x86/hvm/svm/x86_64/exits.S index 1e36baf53d..11c62f9d9e 100644 --- a/xen/arch/x86/hvm/svm/x86_64/exits.S +++ b/xen/arch/x86/hvm/svm/x86_64/exits.S @@ -144,6 +144,8 @@ ENTRY(svm_asm_do_launch) VMLOAD STGI +.globl svm_stgi_label; +svm_stgi_label: movq %rsp,%rdi call svm_vmexit_handler jmp svm_asm_do_resume diff --git a/xen/arch/x86/oprofile/op_model_athlon.c b/xen/arch/x86/oprofile/op_model_athlon.c index c946c1ea8e..1d8f9668f4 100644 --- a/xen/arch/x86/oprofile/op_model_athlon.c +++ b/xen/arch/x86/oprofile/op_model_athlon.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" @@ -44,7 +45,11 @@ static unsigned long reset_value[NUM_COUNTERS]; extern void xenoprof_log_event(struct vcpu *v, unsigned long eip, int mode, int event); - +extern int xenoprofile_get_mode(struct vcpu *v, + struct cpu_user_regs * const regs); + +extern char svm_stgi_label[]; + static void athlon_fill_in_addresses(struct op_msrs * const msrs) { msrs->counters[0].addr = MSR_K7_PERFCTR0; @@ -97,10 +102,9 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs) } } - static int athlon_check_ctrs(unsigned int const cpu, - struct op_msrs const * const msrs, - struct cpu_user_regs * const regs) + struct op_msrs const * const msrs, + struct cpu_user_regs * const regs) { unsigned int low, high; @@ -108,11 +112,19 @@ static int athlon_check_ctrs(unsigned int const cpu, int ovf = 0; unsigned long eip = regs->eip; int mode = 0; - - if (guest_kernel_mode(current, regs)) - mode = 1; - else if (ring_0(regs)) - mode = 2; + struct vcpu *v = current; + struct cpu_user_regs tmp_regs; + + if (!guest_mode(regs) && + (regs->eip == (unsigned long)svm_stgi_label)) { + /* SVM guest was running when NMI occurred */ + hvm_store_cpu_guest_regs(v, &tmp_regs, NULL); + eip = tmp_regs.eip; + mode = xenoprofile_get_mode(v, &tmp_regs); + } else { + eip = regs->eip; + mode = xenoprofile_get_mode(v, regs); + } for (i = 0 ; i < NUM_COUNTERS; ++i) { CTR_READ(low, high, msrs, i); diff --git a/xen/arch/x86/oprofile/op_model_p4.c b/xen/arch/x86/oprofile/op_model_p4.c index 018124eaf9..c285ea1d41 100644 --- a/xen/arch/x86/oprofile/op_model_p4.c +++ b/xen/arch/x86/oprofile/op_model_p4.c @@ -620,9 +620,10 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) } } - extern void xenoprof_log_event(struct vcpu *v, unsigned long eip, int mode, int event); +extern int xenoprofile_get_mode(struct vcpu *v, + struct cpu_user_regs * const regs); static int p4_check_ctrs(unsigned int const cpu, struct op_msrs const * const msrs, @@ -632,12 +633,7 @@ static int p4_check_ctrs(unsigned int const cpu, int i; int ovf = 0; unsigned long eip = regs->eip; - int mode = 0; - - if (guest_kernel_mode(current, regs)) - mode = 1; - else if (ring_0(regs)) - mode = 2; + int mode = xenoprofile_get_mode(current, regs); stag = get_stagger(); diff --git a/xen/arch/x86/oprofile/op_model_ppro.c b/xen/arch/x86/oprofile/op_model_ppro.c index b982443928..139f4571bf 100644 --- a/xen/arch/x86/oprofile/op_model_ppro.c +++ b/xen/arch/x86/oprofile/op_model_ppro.c @@ -88,9 +88,10 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs) } } - extern void xenoprof_log_event(struct vcpu *v, unsigned long eip, int mode, int event); +extern int xenoprofile_get_mode(struct vcpu *v, + struct cpu_user_regs * const regs); static int ppro_check_ctrs(unsigned int const cpu, struct op_msrs const * const msrs, @@ -100,13 +101,8 @@ static int ppro_check_ctrs(unsigned int const cpu, int i; int ovf = 0; unsigned long eip = regs->eip; - int mode = 0; + int mode = xenoprofile_get_mode(current, regs); - if ( guest_kernel_mode(current, regs) ) - mode = 1; - else if ( ring_0(regs) ) - mode = 2; - for (i = 0 ; i < NUM_COUNTERS; ++i) { CTR_READ(low, high, msrs, i); if (CTR_OVERFLOWED(low)) { diff --git a/xen/arch/x86/oprofile/xenoprof.c b/xen/arch/x86/oprofile/xenoprof.c index f60656ba8c..27c2a90297 100644 --- a/xen/arch/x86/oprofile/xenoprof.c +++ b/xen/arch/x86/oprofile/xenoprof.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "op_counter.h" @@ -98,7 +99,7 @@ static void xenoprof_reset_buf(struct domain *d) } } -char *alloc_xenoprof_buf(struct domain *d, int npages) +static char *alloc_xenoprof_buf(struct domain *d, int npages) { char *rawbuf; int i, order; @@ -121,7 +122,8 @@ char *alloc_xenoprof_buf(struct domain *d, int npages) return rawbuf; } -int alloc_xenoprof_struct(struct domain *d, int max_samples, int is_passive) +static int alloc_xenoprof_struct( + struct domain *d, int max_samples, int is_passive) { struct vcpu *v; int nvcpu, npages, bufsize, max_bufsize; @@ -207,7 +209,7 @@ void free_xenoprof_pages(struct domain *d) d->xenoprof = NULL; } -int active_index(struct domain *d) +static int active_index(struct domain *d) { int i; @@ -218,7 +220,7 @@ int active_index(struct domain *d) return -1; } -int set_active(struct domain *d) +static int set_active(struct domain *d) { int ind; struct xenoprof *x; @@ -239,7 +241,7 @@ int set_active(struct domain *d) return 0; } -int reset_active(struct domain *d) +static int reset_active(struct domain *d) { int ind; struct xenoprof *x; @@ -265,7 +267,7 @@ int reset_active(struct domain *d) return 0; } -void reset_passive(struct domain *d) +static void reset_passive(struct domain *d) { struct xenoprof *x; @@ -281,7 +283,7 @@ void reset_passive(struct domain *d) return; } -void reset_active_list(void) +static void reset_active_list(void) { int i; @@ -297,7 +299,7 @@ void reset_active_list(void) activated = 0; } -void reset_passive_list(void) +static void reset_passive_list(void) { int i; @@ -311,7 +313,7 @@ void reset_passive_list(void) pdomains = 0; } -int add_active_list (domid_t domid) +static int add_active_list(domid_t domid) { struct domain *d; @@ -329,7 +331,7 @@ int add_active_list (domid_t domid) return 0; } -int add_passive_list(XEN_GUEST_HANDLE(void) arg) +static int add_passive_list(XEN_GUEST_HANDLE(void) arg) { struct xenoprof_passive passive; struct domain *d; @@ -436,7 +438,7 @@ void xenoprof_log_event( } } -int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg) +static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg) { struct xenoprof_init xenoprof_init; int ret; @@ -458,7 +460,7 @@ int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg) return 0; } -int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg) +static int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg) { struct xenoprof_get_buffer xenoprof_get_buffer; struct domain *d = current->domain; @@ -694,6 +696,17 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg) return ret; } +int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs) +{ + if ( !guest_mode(regs) ) + return 2; + + if ( hvm_guest(v) ) + return ((regs->cs & 3) != 3); + + return guest_kernel_mode(v, regs); +} + /* * Local variables: * mode: C -- 2.30.2